package com.atguigu.gmall.mq.listener;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.mq.config.DeadLetterMqConfig;
import com.atguigu.gmall.mq.config.DelayMessageConfig;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Date;

@Component
@Slf4j
public class ConsumerListener {

    //基于插件的延迟消息
    @RabbitListener(queues = {DelayMessageConfig.queue_delay_1})
    public void receiverDelayedMessage(String msg, Message message, Channel channel) {
        try {
            System.out.println("接收到的延迟消息是:" + msg + ":时间:" + new Date());
            //参数 标识符 是否批量应答
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //基于死信的延迟消息
    @RabbitListener(queues = {DeadLetterMqConfig.queue_dead_2})
    public void receiverDeadLetterMessage(String msg, Message message, Channel channel) {
        try {
            System.out.println("接收到的延迟消息是:" + msg + ":时间:" + new Date());
            //参数 标识符 是否批量应答
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //消息对象组成
    //1 消息属性对象  1.1消息头 1.2消息的其他属性
    //2 消息体
    @RabbitListener(queues = "queue123")
//    @RabbitHandler
    public void receiverMessage(String msg, Message message, Channel channel) {
        try {
            System.out.println("直接接收的消息:" + msg);
            System.out.println("消息对象中的消息体:" + new String(message.getBody()));
//            int i = 10 / 0;
            //手动应答
            //参数 1.消息标识符 2.是否批量应答
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            e.printStackTrace();
            //一旦抛异常
            //1.判断是否是重新发送的消息
            if (message.getMessageProperties().getRedelivered()) {
                //1.1 是旧消息(不要再发了)
                log.error("此消息不能再重新消费了:{}", JSONObject.toJSONString(message));
                //FIFO 为防止阻塞后续消息 直接抹除,
                try {
                    //队列拒绝 则直接剔除该消息
                    channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            } else {
                //1.2 是刚来的消息(只给一次机会) 多次机会的话可借助redis
                log.info("新来的消息 失败后给个机会!");
                try {
                    //requeue 是否重新放到队列中 true 以便消费者重新获取一次消息
                    channel.basicNack(message.getMessageProperties().getDeliveryTag(),
                            false, true);
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
    }
}
